package net.sourceforge.openforecast;

public interface EvaluationModel {
	/** Returns the Akaike Information Criteria obtained from applying the current forecasting model to the initial data
	 * set to try and predict each data point. The result is an indication of the accuracy of the model when applied to
	 * your initial data set - the smaller the Akaike Information Criteria (AIC), the more accurate the model.
	 * 
	 * @return the Akaike Information Criteria (AIC) when the current model was applied to the initial data set.
	 * @since 0.5 */
	/** 赤池信息量准则，即Akaike information criterion、简称AIC。 是衡量统计模型拟合优良性的一种标准，是由日本统计学家赤池弘次创立和发展的。
	 * 赤池信息量准则建立在熵的概念基础上，可以权衡所估计模型的复杂度和此模型拟合数据的优良性。 */
	double getAIC();

	/** Returns the mean absolute deviation obtained from applying the current forecasting model to the initial data set
	 * to try and predict each data point. The result is an indication of the accuracy of the model when applied to your
	 * initial data set - the smaller the Mean Absolute Deviation (MAD), the more accurate the model.
	 * 
	 * @return the mean absolute deviation (MAD) when the current model was applied to the initial data set. */
	/** 平均绝对离差(mean absolute deviation)简称“平均离差”。
	 * 当总体的单位数为N时，有变量X1，X2，X3，……，XN-1，XN，各项变量与总体平均数之差叫离差，平均绝对离差定义为各数据与平均值的离差的绝对值的平均数。 */
	double getMAD();

	/** Returns the mean absolute percentage error obtained from applying the current forecasting model to the initial
	 * data set to try and predict each data point. The result is an indication of the accuracy of the model when
	 * applied to the initial data set - the smaller the Mean Absolute Percentage Error (MAPE), the more accurate the
	 * model.
	 * 
	 * @return the mean absolute percentage error (MAPE) when the current model was applied to the initial data set. */
	// 平均绝对百分比误差
	double getMAPE();

	/** Returns the mean square of the errors (MSE) obtained from applying the current forecasting model to the initial
	 * data set to try and predict each data point. The result is an indication of the accuracy of the model when
	 * applied to your initial data set - the smaller the Mean Square of the Errors, the more accurate the model.
	 * 
	 * @return the mean square of the errors (MSE) when the current model was applied to the initial data set. */
	// 均方差
	double getMSE();

	/** Returns the sum of the absolute errors (SAE) obtained from applying the current forecasting model to the initial
	 * data set to try and predict each data point. The result is an indication of the accuracy of the model when
	 * applied to your initial data set - the smaller the Sum of Absolute Errors, the more accurate the model.
	 * 
	 * @return the sum of the absolute errors (SAE) when the current model was applied to the initial data set. */
	// 绝对误差和
	double getSAE();

	/** Returns the bias - the arithmetic mean of the errors - obtained from applying the current forecasting model to
	 * the initial data set to try and predict each data point. The result is an indication of the accuracy of the model
	 * when applied to your initial data set - the closer the bias is to zero, the more accurate the model.
	 * 
	 * @return the bias - mean of the errors - when the current model was applied to the initial data set. */
	/** 乖离率又称为y值，是反映股价在波动过程中与移动平均线偏离程度的技术指标。 它的理论基础是：不论股价在移动平均线之上或之下，只要偏离距离过远，就会向移动平均线趋近，据此计算股价偏离移动平均线百分比的大小来判断买卖时机。 */
	double getBias();

	public static boolean eval(EvaluationModel m1, EvaluationModel m2) {
		// Default evaluation method is a combination
		int score = 0;

		if (m1.getAIC() - m2.getAIC() <= ForecastConstants.TOLERANCE)
			score++;
		else if (m1.getAIC() - m2.getAIC() >= ForecastConstants.TOLERANCE)
			score--;

		if (m1.getBias() - m2.getBias() <= ForecastConstants.TOLERANCE)
			score++;
		else if (m1.getBias() - m2.getBias() >= ForecastConstants.TOLERANCE)
			score--;

		if (m1.getMAD() - m2.getMAD() <= ForecastConstants.TOLERANCE)
			score++;
		else if (m1.getMAD() - m2.getMAD() >= ForecastConstants.TOLERANCE)
			score--;

		if (m1.getMAPE() - m2.getMAPE() <= ForecastConstants.TOLERANCE)
			score++;
		else if (m1.getMAPE() - m2.getMAPE() >= ForecastConstants.TOLERANCE)
			score--;

		if (m1.getMSE() - m2.getMSE() <= ForecastConstants.TOLERANCE)
			score++;
		else if (m1.getMSE() - m2.getMSE() >= ForecastConstants.TOLERANCE)
			score--;

		if (m1.getSAE() - m2.getSAE() <= ForecastConstants.TOLERANCE)
			score++;
		else if (m1.getSAE() - m2.getSAE() >= ForecastConstants.TOLERANCE)
			score--;

		if (score == 0) {
			// At this point, we're still unsure which one is best
			// so we'll take another approach
			double diff = m1.getAIC() - m2.getAIC();
			diff += m1.getBias() - m2.getBias();
			diff += m1.getMAD() - m2.getMAD();
			diff += m1.getMAPE() - m2.getMAPE();
			diff += m1.getMSE() - m2.getMSE();
			diff += m1.getSAE() - m2.getSAE();

			return (diff < 0);
		} else {
			return (score > 0);
		}
	}
}
